<template>
    <div>
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item>权限管理</el-breadcrumb-item>
            <el-breadcrumb-item>角色列表</el-breadcrumb-item>
        </el-breadcrumb>
        <el-card>
            <el-row>
                <el-col>
                    <el-button type="primary" @click="openDialog">添加角色</el-button>
                </el-col>
            </el-row>
            <el-table :data="rolesList" border style="width: 100%" class="role-table">
                <el-table-column type="expand">
                    <template v-slot="scope">
                        <el-row v-for="level1 in scope.row.children" :key="level1.id">
                            <el-col :span="5">
                                <el-tag
                                    closable
                                    @close="removeRolesRights(scope.row, level1.id)"
                                >{{ level1.authName }}</el-tag>
                                <i class="el-icon-caret-right"></i>
                            </el-col>
                            <el-col :span="19">
                                <el-row v-for="level2 in level1.children" :key="level2.id">
                                    <el-col :span="6">
                                        <el-tag
                                            type="success"
                                            closable
                                            @close="removeRolesRights(scope.row, level2.id)"
                                        >{{ level2.authName }}</el-tag>
                                        <i class="el-icon-caret-right"></i>
                                    </el-col>
                                    <el-col :span="18">
                                        <el-tag
                                            type="warning"
                                            v-for="level3 in level2.children"
                                            :key="level3.id"
                                            closable
                                            @close="removeRolesRights(scope.row, level3.id)"
                                        >{{ level3.authName }}</el-tag>
                                    </el-col>
                                </el-row>
                            </el-col>
                        </el-row>
                    </template>
                </el-table-column>
                <el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
                <el-table-column prop="roleName" label="角色名称"></el-table-column>
                <el-table-column prop="roleDesc" label="角色描述"></el-table-column>
                <el-table-column label="操作" width="300">
                    <template v-slot="scope">
                        <el-button
                            type="primary"
                            size="mini"
                            icon="el-icon-edit"
                            @click="openDialog(scope.row)"
                        >编辑</el-button>
                        <el-button
                            type="danger"
                            size="mini"
                            icon="el-icon-delete"
                            @click="deleteRoles(scope.row)"
                        >删除</el-button>
                        <el-button
                            type="warning"
                            size="mini"
                            icon="el-icon-setting"
                            @click="openSetDialog(scope.row)"
                        >分配权限</el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <!-- 添加角色 -->
        <el-dialog
            :title="rolesTitle"
            :visible.sync="rolesDialogVisible"
            width="50%"
            @close="rolesDialogClose"
        >
            <el-form :model="rolesForm" :rules="rolesRules" ref="rolesRef" label-width="80px">
                <el-form-item label="角色名称" prop="roleName">
                    <el-input v-model="rolesForm.roleName"></el-input>
                </el-form-item>
                <el-form-item label="角色描述" prop="roleDesc">
                    <el-input v-model="rolesForm.roleDesc"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="rolesDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="saveRoles">确 定</el-button>
            </span>
        </el-dialog>
        <!-- 分配权限 -->
        <el-dialog
            title="分配权限"
            :visible.sync="setRightDialogVisible"
            width="50%"
            class="dialog-flex dialog-flex-footer"
            @close="closeRightDialog"
        >
            <el-tree
                :data="rightsList"
                :props="treeProps"
                show-checkbox
                node-key="id"
                default-expand-all
                :default-checked-keys="treeCheckedKeys"
                ref="treeRef"
            ></el-tree>
            <span slot="footer" class="dialog-footer">
                <el-button @click="setRightDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="saveRights">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
export default {
    data() {
        return {
            rolesList: [],
            rolesDialogVisible: false,
            rolesForm: {
                roleId: 0,
                roleName: '',
                roleDesc: ''
            },
            rolesRules: {
                roleName: [
                    { required: true, message: '请输入角色名称', trigger: 'blur' }
                ],
                roleDesc: [
                    { required: true, message: '请输入角色描述', trigger: 'blur' }
                ]
            },
            rolesTitle: '',
            setRightDialogVisible: false,
            rightsList: [],
            // 属性控件的属性绑定对象
            treeProps: {
                label: 'authName',
                children: 'children'
            },
            treeCheckedKeys: [],
            roleId: ''
        }
    },
    methods: {
        // 列表数据
        async getRolesList() {
            const { data: res } = await this.$http.get('roles')
            if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
            this.rolesList = res.data
        },
        // 添加/修改角色窗口
        async openDialog(rolesInfo) {
            this.rolesDialogVisible = true
            if (rolesInfo.id > 0) {
                this.rolesTitle = '编辑角色'
                const { data: res } = await this.$http.get('roles/' + rolesInfo.id)
                if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
                this.rolesForm = res.data
            } else {
                this.rolesTitle = '添加角色'
            }
        },
        // 保存角色信息
        saveRoles() {
            this.$refs.rolesRef.validate(async valid => {
                if (!valid) return
                // 编辑角色信息
                if (this.rolesForm.roleId > 0) {
                    const { data: res } = await this.$http.put('roles/' + this.rolesForm.roleId, this.rolesForm)
                    if (res.meta.status !== 200) this.$message.error(res.meta.msg)
                    this.$message.success('编辑角色信息成功!')
                } else {    // 添加角色信息
                    const { data: res } = await this.$http.post('roles', this.rolesForm)
                    if (res.meta.status !== 201) this.$message.error(res.meta.msg)
                    this.$message.success(res.meta.msg)
                }
                this.getRolesList()
                this.rolesDialogVisible = false
            })
        },
        // 删除角色
        async deleteRoles(rolesInfo) {
            const confirmRes = await this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
                type: 'warning'
            }).catch(err => err)
            if (confirmRes !== 'confirm') return this.$message.info('已取消删除')
            const { data: res } = await this.$http.delete('roles/' + rolesInfo.id)
            if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
            this.$message.success(res.meta.msg)
            this.getRolesList()
        },
        // 关闭角色窗口（重置表单）
        rolesDialogClose() {
            this.rolesForm.roleId = 0
            this.$refs.rolesRef.resetFields()
        },
        // 移除权限
        async removeRolesRights(role, rid) {
            const confirmRes = await this.$confirm('确定对该角色移除此权限吗?', '提示', {
                type: 'warning'
            }).catch(err => err)
            if (confirmRes !== 'confirm') return this.$message.info('已取消移除权限')
            const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${rid}`)
            if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
            this.$message.success(res.meta.msg)
            // this.getRolesList()
            role.children = res.data
        },
        // 分配权限窗口
        async openSetDialog(role) {
            this.roleId = role.id
            const { data: res } = await this.$http.get('rights/tree')
            this.rightsList = res.data
            this.getTreeCheckedKeys(role, this.treeCheckedKeys)
            this.setRightDialogVisible = true
        },
        // 通过递归形式，获取角色下所有权限的id，并保存到数组中
        getTreeCheckedKeys(node, arr) {
            if (!node.children) {
                return arr.push(node.id)
            }
            node.children.forEach(item => this.getTreeCheckedKeys(item, arr))
        },
        // 监听分配权限关闭窗口
        closeRightDialog() {
            this.treeCheckedKeys = []
            this.roleId = ''
        },
        // 保存分配权限
        async saveRights() {
            let keys = [
                ...this.$refs.treeRef.getCheckedKeys(),
                ...this.$refs.treeRef.getHalfCheckedKeys()
            ]
            const idStr = keys.join(',')
            const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, {
                rids: idStr
            })
            if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
            this.$message.success(res.meta.msg)
            this.getRolesList()
            this.setRightDialogVisible = false
        }
    },
    created() {
        this.getRolesList()
    },
}
</script>
<style lang="less">
.role-table .el-table__expanded-cell[class*='cell'] {
    padding: 0;
}
.dialog-flex {
    .flexbox();
    .align-items(center);
    .justify-content(center);
    .el-dialog {
        margin: 0 auto !important;
        height: 90%;
        overflow: hidden;
        .el-dialog__body {
            position: absolute;
            left: 0;
            top: 54px;
            bottom: 0;
            right: 0;
            padding: 0 20px;
            z-index: 1;
            overflow: hidden;
            overflow-y: auto;
        }
    }
}
.dialog-flex-footer {
    .el-dialog {
        .el-dialog__body {
            bottom: 70px;
        }
        .el-dialog__footer {
            position: absolute;
            left: 0;
            bottom: 0;
            right: 0;
            z-index: 1;
        }
    }
}
</style>
<style lang="less" scoped>
.role-table {
    .el-row {
        background-color: @gray-bg;
        .flexbox();
        .align-items(center);
        .hairline(bottom, @gray-line);
        &:last-child {
            .hairline-remove(bottom);
        }
        .el-col {
            position: relative;
            .hairline(left, @gray-line);
            &:first-child {
                .hairline-remove(left);
            }
        }
        .el-col-5,
        .el-col-6,
        .el-col-18 {
            padding-top: 5px;
            text-align: center;
            .el-tag {
                margin-bottom: 5px;
                margin-left: 10px;
                &:first-child {
                    margin-left: 0;
                }
            }
        }
        .el-col-18 {
            text-align: left;
            .el-tag {
                margin-left: 10px;
                &:first-child {
                    margin-left: 10px;
                }
            }
        }
    }
}
</style>